#include <boost/smart_ptr.hpp>
#include <iostream>
#include "block_queue.h"

using namespace std;
using namespace boost;

void test_single_thread();
void test_multi_thread1();
void test_multi_thread2();

int main(int argc, char* argv[])
{

    cout << "test_single_thread begin." << endl;
    test_single_thread();
    cout << "test_single_thread done." << endl;

    cout << "test_multi_thread1 begin." << endl;
    test_multi_thread1();
    cout << "test_multi_thread1 done." << endl;

    cout << "test_multi_thread2 begin." << endl;
    test_multi_thread2();
    cout << "test_multi_thread2 done." << endl;


	system("pause");
	return 0;
}

void test_single_thread()
{
    int* a = new int(1);
    int* b = new int(2);
    int* c = new int(3);
    block_queue<int> bq(100);
    bq.put(shared_ptr<int>(a));
    bq.put(shared_ptr<int>(b));
    bq.put(shared_ptr<int>(c));

    cout << "size=" << bq.get_size() << endl;
    cout << "a=" << *(bq.get()) << endl;
    cout << "size=" << bq.get_size() << endl;
    cout << "b=" << *(bq.get()) << endl;
    cout << "size=" << bq.get_size() << endl;
    cout << "c=" << *(bq.get()) << endl;
}

struct do_get_it 
{

    block_queue<int> *bq;

    void operator ()()
    {
        cout << "thread " << this_thread::get_id() << " started." << endl;
        while(true)
        {
            shared_ptr<int> el = bq->get();
            if(el.get() != NULL){
                cout << "get=" << *(el) << endl;
            } else {
                break;
            }
        }
        cout << "thread " << this_thread::get_id() << " to end." << endl;
    }
};

void test_multi_thread1()
{
    block_queue<int> *que = new block_queue<int>(10);
    do_get_it dgi;
    dgi.bq = que;

    boost::thread t1(dgi);

    for(int i = 0; i < 5; ++i){
        system_time end_time = get_system_time() + posix_time::milliseconds(2000);
        this_thread::sleep(end_time);
        que->put(shared_ptr<int>(new int(i)));
    }

    delete que;

    t1.join();

}

struct do_put_it 
{

    block_queue<int> *que;

    void operator ()()
    {
        cout << "thread " << this_thread::get_id() << " started." << endl;
        for(int i=0; i < 5; i++)
        {
            shared_ptr<int> el(new int(i));
            cout << "try to put= " << *el << endl;
            int rv = que->put(el);
            cout << "result= " << rv << endl;
            if(rv < 0){
                break;
            }
            cout << "put= " << *el << endl;
        }
        cout << "thread " << this_thread::get_id() << " to end." << endl;
        que->dispose();
    }
};

void test_multi_thread2()
{
    block_queue<int> *que = new block_queue<int>(2);
    do_put_it dpi;
    dpi.que = que;

    boost::thread t1(dpi);

    while(true){
        system_time end_time = get_system_time() + posix_time::milliseconds(2000);
        this_thread::sleep(end_time);
        shared_ptr<int> el = que->get();
        if(!el){
            break;
        }
    }

    t1.join();
    delete que;
}
